{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 5. Kernelizing the Perceptron\n",
    "\n",
    "## (a)\n",
    "\n",
    "### i.\n",
    "\n",
    "Because the algorithm only makes one pass through the training set, it will always be the case that $\\theta^{(i)}$ is a linear combination of $\\phi(x^{(1)}), \\ldots, \\phi(x^{(i)})$, i.e."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "$$ \\theta^{(i)} = \\sum_{k=1}^i \\theta_k \\phi(x^{(k)})$$"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "for some real numbers $\\theta_k\\in \\mathbb R$."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Therefore we could represent $\\theta^{(i)}$ by the list $[\\theta_1,\\ldots, \\theta_i]$. For technical reasons we will instead represent $\\theta^{(i)}$ by the pair $([\\theta_1,\\ldots, \\theta_i], [x^{(1)},\\ldots, x^{(i)}])$."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "In particular $\\theta^{(0)}=0$ will be represented by $([], [])$, i.e. a pair of two empty lists."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### ii.\n",
    "\n",
    "For any vector $x\\in \\mathbb R^n$ and any vector $\\theta$ with \n",
    "$$ \\theta = \\sum_{k=1}^i \\theta_k \\phi(x^{(k)})$$\n",
    "we have"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "$$ \\begin{align*}\n",
    " \\theta^T \\phi(x) &= \\sum_{k=1}^i \\theta_k \\phi(x^{(k)})^T \\phi(x) \\\\\n",
    " &= \\sum_{k=1}^i \\theta_k K(x^{(k)}, x).\n",
    "\\end{align*}$$"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "So for a new input $x^{i+1}$ we can compute the prediction efficiently by "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "$$\\begin{align*} h_{\\theta^{(i)}}(x^{(i+1)}) &= g\\left( \\theta^{(i)T}\\phi(x^{(i+1)}\\right)\\\\\n",
    "&= g\\left(\\sum_{k=1}^i \\theta^{(i)}_k K(x^{(k)}, x^{(i+1)})\\right)\n",
    "\\end{align*}$$"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### iii.\n",
    "\n",
    "The new update rule \n",
    "$$ \\theta^{(i+1)} := \\theta^{(i)} + \\alpha(y^{(i+1)} - h_{\\theta^{(i)}}(x^{(i+1)}))\\phi(x^{(i+1)})$$"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "can be implemented by appending \n",
    "\n",
    "$$\\theta_{i+1}:=\\alpha(y^{(i+1)} - h_{\\theta^{(i)}}(x^{(i+1)})) $$\n",
    "\n",
    "resp. $x^{(i+1)}$ to the first resp. second component of our representation $([\\theta_1,\\ldots, \\theta_i], [x^{(1)}, \\ldots, x^{(i)}])$ of $\\theta^{(i)}$."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## (b)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import math\n",
    "\n",
    "import matplotlib.pyplot as plt\n",
    "import numpy as np\n",
    "\n",
    "import src.util as util"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The provided code for the sign and kernel functions (no changes made):"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "def sign(a):\n",
    "    \"\"\"Gets the sign of a scalar input.\"\"\"\n",
    "    if a >= 0:\n",
    "        return 1\n",
    "    else:\n",
    "        return 0\n",
    "\n",
    "\n",
    "def dot_kernel(a, b):\n",
    "    \"\"\"An implementation of a dot product kernel.\n",
    "\n",
    "    Args:\n",
    "        a: A vector\n",
    "        b: A vector\n",
    "    \"\"\"\n",
    "    return np.dot(a, b)\n",
    "\n",
    "\n",
    "def rbf_kernel(a, b, sigma=1):\n",
    "    \"\"\"An implementation of the radial basis function kernel.\n",
    "\n",
    "    Args:\n",
    "        a: A vector\n",
    "        b: A vector\n",
    "        sigma: The radius of the kernel\n",
    "    \"\"\"\n",
    "    distance = (a - b).dot(a - b)\n",
    "    scaled_distance = -distance / (2 * (sigma) ** 2)\n",
    "    return math.exp(scaled_distance)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Define the initial state as a pair of two empty numpy arrays:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "def initial_state():\n",
    "    \"\"\"Return the initial state for the perceptron.\n",
    "\n",
    "    This function computes and then returns the initial state of the perceptron.\n",
    "    Feel free to use any data type (dicts, lists, tuples, or custom classes) to\n",
    "    contain the state of the perceptron.\n",
    "\n",
    "    \"\"\"\n",
    "\n",
    "    # *** START CODE HERE ***\n",
    "    return (np.array([]).reshape((0,)), np.array([]).reshape((0,2)))\n",
    "    # *** END CODE HERE ***"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Implement predictions according to the formula from (a)ii.:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "def predict(state, kernel, x_i):\n",
    "    \"\"\"Peform a prediction on a given instance x_i given the current state\n",
    "    and the kernel.\n",
    "\n",
    "    Args:\n",
    "        state: The state returned from initial_state()\n",
    "        kernel: A binary function that takes two vectors as input and returns\n",
    "            the result of a kernel\n",
    "        x_i: A vector containing the features for a single instance\n",
    "    \n",
    "    Returns:\n",
    "        Returns the prediction (i.e 0 or 1)\n",
    "    \"\"\"\n",
    "    # *** START CODE HERE ***\n",
    "    theta, x = state\n",
    "    \n",
    "    # compute scalar products of phi(x_k) and phi(x_i)\n",
    "    K = np.array([kernel(x_k,x_i) for x_k in x])\n",
    "    \n",
    "    # implement the sum from (a)ii. as a scalar product\n",
    "    return sign(theta @ K)\n",
    "    # *** END CODE HERE ***"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Implement the update rule from (a)iii.:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "def update_state(state, kernel, learning_rate, x_i, y_i):\n",
    "    \"\"\"Updates the state of the perceptron.\n",
    "\n",
    "    Args:\n",
    "        state: The state returned from initial_state()\n",
    "        kernel: A binary function that takes two vectors as input and returns the result of a kernel\n",
    "        learning_rate: The learning rate for the update\n",
    "        x_i: A vector containing the features for a single instance\n",
    "        y_i: A 0 or 1 indicating the label for a single instance\n",
    "    \"\"\"\n",
    "    # *** START CODE HERE ***    \n",
    "    theta_i = learning_rate * (y_i - predict(state, kernel, x_i))\n",
    "    \n",
    "    theta, x = state\n",
    "    theta_new = np.append(theta, [theta_i], axis = 0)\n",
    "    x_new = np.append(x, [x_i], axis=0)\n",
    "    return (theta_new, x_new)\n",
    "    # *** END CODE HERE ***\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## (c)\n",
    "\n",
    "I adapted the provided code for training to not save the results but instead show the plots directly as well as the accuracy on the test set:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "def train_perceptron(kernel_name, kernel, learning_rate):\n",
    "    \"\"\"Train a perceptron with the given kernel.\n",
    "\n",
    "    This function trains a perceptron with a given kernel and then\n",
    "    uses that perceptron to make predictions.\n",
    "\n",
    "    Args:\n",
    "        kernel: The kernel function.\n",
    "        learning_rate: The learning rate for training.\n",
    "    \"\"\"\n",
    "    train_x, train_y = util.load_csv('data/ds5_train.csv')\n",
    "\n",
    "    state = initial_state()\n",
    "\n",
    "    for x_i, y_i in zip(train_x, train_y):\n",
    "        state = update_state(state, kernel, learning_rate, x_i, y_i)\n",
    "    \n",
    "    test_x, test_y = util.load_csv('data/ds5_train.csv')\n",
    "\n",
    "    plt.figure(figsize=(12, 8))\n",
    "    util.plot_contour(lambda a: predict(state, kernel, a))\n",
    "    util.plot_points(train_x,train_y)\n",
    "    predict_y = [predict(state, kernel, test_x[i, :]) for i in range(test_y.shape[0])]\n",
    "    accuracy = np.mean(predict_y == test_y)\n",
    "    print(\"Accuracy with {} kernel on test set: {}\".format(kernel_name, accuracy))\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Train a perceptron kernelized with a dot product kernel:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Accuracy with dot kernel on test set: 0.48\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 864x576 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "train_perceptron('dot', dot_kernel, 0.5)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Train a perceptron kernelized with radial basis function kernel:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Accuracy with rbf kernel on test set: 0.945\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 864x576 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "train_perceptron('rbf', rbf_kernel, 0.5)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "With the dot product kernel the perceptron performs very poorly, because the model is trying to find a linear decision boundary but the dataset is far from linearly separable."
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.10"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
